﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.DirectoryServices;
using System.Security.Principal;
using System.Runtime.InteropServices;

namespace ExternalTokenAnalysisOffline
{
    public partial class Form1 : Form
    {
        [DllImport("advapi32.dll")]
        public static extern int ConvertSidToStringSid(byte[] psid, ref IntPtr stringSid);

        public Form1()
        {
            InitializeComponent();
        }

        private bool IsFormAuth(byte[] externaltoken)
        {
            bool _isFormAuth = false;

            try
            {
                // size
                byte[] size = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    size[cnt] = externaltoken[cnt];
                }
                UInt32 _size = BitConverter.ToUInt32(size, 0);
                //dict["Size"] = _size.ToString();

                //magic
                byte[] magic = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    magic[cnt] = externaltoken[4 + cnt];
                }
                string _magic = BitConverter.ToString(magic);
                string[] _magics = _magic.Split('-');
                Array.Reverse(_magics);
                string _magicStr = "";
                foreach (string s in _magics)
                {
                    _magicStr += s;
                }
                //dict["Magic"] = _magicStr;

                //AuthType
                byte[] type = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    type[cnt] = externaltoken[8 + cnt];
                }
                UInt32 _type = BitConverter.ToUInt32(type, 0);
                //dict["AuthenticationType"] = _type.ToString();
                if (_type == 1)
                {
                    _isFormAuth = false;
                }
                else
                {
                    _isFormAuth = true;
                }
            }
            catch { }

            return _isFormAuth;
        }

        private Dictionary<string, string> AnalyzeTokenAD(byte[] externaltoken)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();

            try
            {
                // size
                byte[] size = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    size[cnt] = externaltoken[cnt];
                }
                UInt32 _size = BitConverter.ToUInt32(size, 0);
                dict["Size"] = _size.ToString();

                //magic
                byte[] magic = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    magic[cnt] = externaltoken[4 + cnt];
                }
                string _magic = BitConverter.ToString(magic);
                string[] _magics = _magic.Split('-');
                Array.Reverse(_magics);
                string _magicStr = "";
                foreach (string s in _magics)
                {
                    _magicStr += s;
                }
                dict["Magic"] = _magicStr;

                //AuthType
                byte[] type = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    type[cnt] = externaltoken[8 + cnt];
                }
                UInt32 _type = BitConverter.ToUInt32(type, 0);
                dict["AuthenticationType"] = _type.ToString();

                //UserSystemIdSize
                byte[] UserSystemIdSize = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    UserSystemIdSize[cnt] = externaltoken[12 + cnt];
                }
                UInt32 _UserSystemIdSize = BitConverter.ToUInt32(UserSystemIdSize, 0);
                dict["UserSystemIdSize"] = _UserSystemIdSize.ToString();

                //TokenGroupSize
                byte[] TokenGroupSize = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    TokenGroupSize[cnt] = externaltoken[16 + cnt];
                }
                UInt32 _TokenGroupSize = BitConverter.ToUInt32(TokenGroupSize, 0);
                dict["TokenGroupsSize"] = _TokenGroupSize.ToString();

                //TimerTokenGenerated
                byte[] TimerToken = new byte[8];
                for (int cnt = 0; cnt < 8; cnt++)
                {
                    TimerToken[cnt] = externaltoken[20 + cnt];
                }
                byte[] TimerToken2 = new byte[8];
                TimerToken2[0] = TimerToken[4];
                TimerToken2[1] = TimerToken[5];
                TimerToken2[2] = TimerToken[6];
                TimerToken2[3] = TimerToken[7];
                TimerToken2[4] = TimerToken[0];
                TimerToken2[5] = TimerToken[1];
                TimerToken2[6] = TimerToken[2];
                TimerToken2[7] = TimerToken[3];
                UInt32 _TimerToken = BitConverter.ToUInt32(TimerToken2, 0);
                DateTime utc = new DateTime(1899, 1, 1);
                DateTime _TimerTokenDT = utc.AddSeconds((double)_TimerToken);
                dict["TimeTokenGenerated"] = _TimerTokenDT.ToString("yyyy/MM/dd hh:mm:ss");

                //UserSystemId
                string _UserSystemId = "";
                byte[] UserSystemId = new byte[_UserSystemIdSize];
                for (int cnt = 0; cnt < _UserSystemIdSize; cnt++)
                {
                    UserSystemId[cnt] = externaltoken[28 + 4 + cnt];
                    _UserSystemId += string.Format("{0,0:X2}", UserSystemId[cnt]);
                }
                dict["UserSystemId"] = _UserSystemId;
                if (this.checkBox1.Checked)
                {
                    dict["UserSystemId"] = GetEntry(UserSystemId);
                }

                //TokenGroups
                byte[] TokenGroups = new byte[_TokenGroupSize];
                for (int cnt = 0; cnt < _TokenGroupSize; cnt++)
                {
                    TokenGroups[cnt] = externaltoken[28 + 4 + _UserSystemIdSize + cnt];
                }
                if (TokenGroups.Length > 0)
                {
                    //GroupCount
                    byte[] GroupCount = new byte[4];
                    for (int cnt = 0; cnt < 4; cnt++)
                    {
                        GroupCount[cnt] = TokenGroups[cnt];
                    }
                    UInt32 _GroupCount = BitConverter.ToUInt32(GroupCount, 0);
                    dict["GroupCount"] = _GroupCount.ToString();

                    //OffsetsAndAttributes
                    byte[] OffsetsAndAttributes = new byte[_GroupCount * 8];
                    for (int cnt = 0; cnt < OffsetsAndAttributes.Length; cnt++)
                    {
                        OffsetsAndAttributes[cnt] = TokenGroups[4 + cnt];
                    }
                    for (int cnt1 = 0; cnt1 < _GroupCount; cnt1++)
                    {
                        //Offset
                        byte[] Offset = new byte[4];
                        for (int cnt2 = 0; cnt2 < 4; cnt2++)
                        {
                            Offset[cnt2] = OffsetsAndAttributes[cnt1 * 8 + cnt2];
                        }
                        UInt32 _Offset = BitConverter.ToUInt32(Offset, 0);
                        //Attributes
                        byte[] Attributes = new byte[4];
                        for (int cnt2 = 0; cnt2 < 4; cnt2++)
                        {
                            try
                            {
                                Attributes[cnt2] = OffsetsAndAttributes[(cnt1 + 1) * 8 + cnt2];
                            }
                            catch { }
                        }
                        UInt32 _Attributes = BitConverter.ToUInt32(Attributes, 0);

                        byte[] GroupSystemId = null;
                        string _GroupSystemId = "";
                        if (_Attributes != 0)
                        {
                            GroupSystemId = new byte[_Attributes];
                            for (int cnt3 = 0; cnt3 < _Attributes - _Offset; cnt3++)
                            {
                                GroupSystemId[cnt3] = TokenGroups[_Offset + cnt3];
                                _GroupSystemId += string.Format("{0,0:X2}", GroupSystemId[cnt3]);
                            }
                        }
                        else
                        {
                            GroupSystemId = new byte[TokenGroups.Length - _Offset];
                            for (int cnt3 = 0; cnt3 < TokenGroups.Length - _Offset; cnt3++)
                            {
                                GroupSystemId[cnt3] = TokenGroups[_Offset + cnt3];
                                _GroupSystemId += string.Format("{0,0:X2}", GroupSystemId[cnt3]);
                            }
                        }
                        dict["GroupSystemId" + cnt1.ToString()] = _GroupSystemId;
                        if (this.checkBox1.Checked)
                        {
                            dict["GroupSystemId" + cnt1.ToString()] = this.GetEntry(GroupSystemId);
                        }
                        else
                        {
                            dict["GroupSystemId" + cnt1.ToString()] = _GroupSystemId + "(" + this.ToObjectSidString(GroupSystemId) +")";
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
            }

            return dict;
        }

        private Dictionary<string, string> AnalyzeTokenFormAuth(byte[] externaltoken)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();

            try
            {
                // size
                byte[] size = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    size[cnt] = externaltoken[cnt];
                }
                UInt32 _size = BitConverter.ToUInt32(size, 0);
                dict["Size"] = _size.ToString();

                //magic
                byte[] magic = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    magic[cnt] = externaltoken[4 + cnt];
                }
                string _magic = BitConverter.ToString(magic);
                string[] _magics = _magic.Split('-');
                Array.Reverse(_magics);
                string _magicStr = "";
                foreach (string s in _magics)
                {
                    _magicStr += s;
                }
                dict["Magic"] = _magicStr;

                //AuthType
                byte[] type = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    type[cnt] = externaltoken[8 + cnt];
                }
                UInt32 _type = BitConverter.ToUInt32(type, 0);
                dict["AuthenticationType"] = _type.ToString();

                //UserSystemIdSize
                byte[] UserSystemIdSize = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    UserSystemIdSize[cnt] = externaltoken[12 + cnt];
                }
                UInt32 _UserSystemIdSize = BitConverter.ToUInt32(UserSystemIdSize, 0);
                dict["UserSystemIdSize"] = _UserSystemIdSize.ToString();

                //TokenGroupSize
                byte[] TokenGroupSize = new byte[4];
                for (int cnt = 0; cnt < 4; cnt++)
                {
                    TokenGroupSize[cnt] = externaltoken[16 + cnt];
                }
                UInt32 _TokenGroupSize = BitConverter.ToUInt32(TokenGroupSize, 0);
                dict["TokenGroupsSize"] = _TokenGroupSize.ToString();

                //TimerTokenGenerated
                byte[] TimerToken = new byte[8];
                for (int cnt = 0; cnt < 8; cnt++)
                {
                    TimerToken[cnt] = externaltoken[20 + cnt];
                }
                byte[] TimerToken2 = new byte[8];
                TimerToken2[0] = TimerToken[4];
                TimerToken2[1] = TimerToken[5];
                TimerToken2[2] = TimerToken[6];
                TimerToken2[3] = TimerToken[7];
                TimerToken2[4] = TimerToken[0];
                TimerToken2[5] = TimerToken[1];
                TimerToken2[6] = TimerToken[2];
                TimerToken2[7] = TimerToken[3];
                UInt32 _TimerToken = BitConverter.ToUInt32(TimerToken2, 0);
                DateTime utc = new DateTime(1899, 1, 1);
                DateTime _TimerTokenDT = utc.AddSeconds((double)_TimerToken);
                dict["TimeTokenGenerated"] = _TimerTokenDT.ToString("yyyy/MM/dd hh:mm:ss");

                //UserSystemId
                byte[] UserSystemId = new byte[_UserSystemIdSize];
                for (int cnt = 0; cnt < _UserSystemIdSize; cnt++)
                {
                    UserSystemId[cnt] = externaltoken[28 + 4 + cnt];
                }
                //string _UserSystemId = Encoding.Default.GetString(UserSystemId);
                string _UserSystemId = Encoding.ASCII.GetString(UserSystemId);
                dict["UserSystemId"] = _UserSystemId + "=" + this.GetEntry(UserSystemId);

                //TokenGroups
                byte[] TokenGroups = new byte[_TokenGroupSize];
                for (int cnt = 0; cnt < _TokenGroupSize; cnt++)
                {
                    TokenGroups[cnt] = externaltoken[28 + 4 + _UserSystemIdSize + cnt];
                }
                if (TokenGroups.Length > 0)
                {
                    //GroupCount
                    byte[] GroupCount = new byte[4];
                    for (int cnt = 0; cnt < 4; cnt++)
                    {
                        GroupCount[cnt] = TokenGroups[cnt];
                    }
                    UInt32 _GroupCount = BitConverter.ToUInt32(GroupCount, 0);
                    dict["GroupCount"] = _GroupCount.ToString();

                    //OffsetsAndAttributes
                    byte[] OffsetsAndAttributes = new byte[_GroupCount * 8];
                    for (int cnt = 0; cnt < OffsetsAndAttributes.Length; cnt++)
                    {
                        OffsetsAndAttributes[cnt] = TokenGroups[4 + cnt];
                    }
                    for (int cnt1 = 0; cnt1 < _GroupCount; cnt1++)
                    {
                        //Offset
                        byte[] Offset = new byte[4];
                        for (int cnt2 = 0; cnt2 < 4; cnt2++)
                        {
                            Offset[cnt2] = OffsetsAndAttributes[cnt1 * 8 + cnt2];
                        }
                        UInt32 _Offset = BitConverter.ToUInt32(Offset, 0);

                        //Attributes
                        byte[] Attributes = new byte[4];
                        for (int cnt2 = 0; cnt2 < 4; cnt2++)
                        {
                            Attributes[cnt2] = OffsetsAndAttributes[cnt1 * 8 + 4 + cnt2];
                        }
                        UInt32 _Attributes = BitConverter.ToUInt32(Attributes, 0);

                        byte[] GroupSystemId = new byte[_Attributes];
                        for (int cnt3 = 0; cnt3 < _Attributes; cnt3++)
                        {
                            GroupSystemId[cnt3] = TokenGroups[_Offset + cnt3];
                        }
                        string _GroupSystemId = Encoding.UTF8.GetString(GroupSystemId);
                        dict["GroupSystemId" + cnt1.ToString()] = _GroupSystemId;
                    }
                }

            }
            catch { }

            return dict;
        }

        private string ToObjectSidString(byte[] bytes)
        {
            string stringSid = "";
            IntPtr pStringSid = IntPtr.Zero;

            int ret = ConvertSidToStringSid(bytes, ref pStringSid);

            if (ret != 0)
            {
                stringSid = Marshal.PtrToStringAnsi(pStringSid);
                Marshal.FreeCoTaskMem(pStringSid);
            }

            return stringSid;
        }

        private string GetSystemSid(string sid)
        {
            string name = "";
            switch (sid)
            {
                case "S-1-0-0":
                    name= "NULL";
                    break;
                case "S-1-1-0":
                    name= "EVERYONE";
                    break;
                case "S-1-2-0":
                    name = "LOCAL";
                    break;
                case "S-1-2-1":
                    name = "CONSOLE_LOGON";
                    break;
                case "S-1-3-0":
                    name = "CREATOR_OWNER";
                    break;
                case "S-1-3-1":
                    name = "CREATOR_GROUP";
                    break;
                case "S-1-3-2":
                    name = "OWNER_SERVER";
                    break;
                case "GROUP_SERVER":
                    name = "S-1-3-3";
                    break;
                case "OWNER_RIGHTS":
                    name = "S-1-3-4";
                    break;
                case "S-1-5":
                    name = "NT_AUTHORITY";
                    break;
                case "S-1-5-1":
                    name = "DIALUP";
                    break;
                case "NETWORK":
                    name = "S-1-5-2";
                    break;
                case "S-1-5-3":
                    name = "BATCH";
                    break;
                case "S-1-5-4":
                    name = "INTERACTIVE";
                    break;
                case "S-1-5-6":
                    name = "SERVICE";
                    break;
                case "S-1-5-7":
                    name = "ANONYMOUS";
                    break;
                case "S-1-5-8":
                    name = "PROXY";
                    break;
                case "S-1-5-9":
                    name = "ENTERPRISE_DOMAIN_CONTROLLERS";
                    break;
                case "S-1-5-10":
                    name = "PRINCIPAL_SELF";
                    break;
                case "S-1-5-11":
                    name = "AUTHENTICATED_USERS";
                    break;
                case "S-1-5-12":
                    name = "RESTRICTED_CODE";
                    break;
                case "S-1-5-13":
                    name = "TERMINAL_SERVER_USER";
                    break;
                case "S-1-5-14":
                    name = "REMOTE_INTERACTIVE_LOGON";
                    break;
                case "S-1-5-15":
                    name = "THIS_ORGANIZATION";
                    break;
                case "S-1-5-17":
                    name = "IUSR";
                    break;
                case "S-1-5-18":
                    name = "LOCAL_SYSTEM";
                    break;
                case "S-1-5-19":
                    name = "LOCAL_SERVICE";
                    break;
                case "S-1-5-20":
                    name = "NETWORK_SERVICE";
                    break;
                case "S-1-5-21-0-0-0-496":
                    name = "COMPOUNDED_AUTHENTICATION";
                    break;
                case "S-1-5-21-0-0-0-497":
                    name = "CLAIMS_VALID";
                    break;
                case "S-1-5-32-544":
                    name = "BUILTIN_ADMINISTRATORS";
                    break;
                case "S-1-5-32-545":
                    name = "BUILTIN_USERS";
                    break;
                case "S-1-5-32-546":
                    name = "BUILTIN_GUESTS";
                    break;
                case "S-1-5-32-547":
                    name = "POWER_USERS";
                    break;
                case "S-1-5-32-548":
                    name = "ACCOUNT_OPERATORS";
                    break;
                case "S-1-5-32-549":
                    name = "SERVER_OPERATORS";
                    break;
                case "S-1-5-32-550":
                    name = "PRINTER_OPERATORS";
                    break;
                case "S-1-5-32-551":
                    name = "BACKUP_OPERATORS";
                    break;
                case "S-1-5-32-552":
                    name = "REPLICATOR";
                    break;
                case "S-1-5-32-554":
                    name = "ALIAS_PREW2KCOMPACC";
                    break;
                case "S-1-5-32-555":
                    name = "REMOTE_DESKTOP";
                    break;
                case "S-1-5-32-556":
                    name = "NETWORK_CONFIGURATION_OPS";
                    break;
                case "S-1-5-32-557":
                    name = "INCOMING_FOREST_TRUST_BUILDERS";
                    break;
                case "S-1-5-32-558":
                    name = "PERFMON_USERS";
                    break;
                case "S-1-5-32-559":
                    name = "PERFLOG_USERS";
                    break;
                case "S-1-5-32-560":
                    name = "WINDOWS_AUTHORIZATION_ACCESS_GROUP";
                    break;
                case "S-1-5-32-561":
                    name = "TERMINAL_SERVER_LICENSE_SERVERS";
                    break;
                case "S-1-5-32-562":
                    name = "DISTRIBUTED_COM_USERS";
                    break;
                case "S-1-5-32-568":
                    name = "IIS_IUSRS";
                    break;
                case "S-1-5-32-569":
                    name = "CRYPTOGRAPHIC_OPERATORS";
                    break;
                case "S-1-5-32-573":
                    name = "EVENT_LOG_READERS";
                    break;
                case "S-1-5-32-574":
                    name = "CERTIFICATE_SERVICE_DCOM_ACCESS";
                    break;
                case "S-1-5-32-575":
                    name = "RDS_REMOTE_ACCESS_SERVERS";
                    break;
                case "S-1-5-32-576":
                    name = "RDS_ENDPOINT_SERVERS";
                    break;
                case "S-1-5-32-577":
                    name = "RDS_MANAGEMENT_SERVERS";
                    break;
                case "S-1-5-32-578":
                    name = "HYPER_V_ADMINS";
                    break;
                case "S-1-5-32-579":
                    name = "ACCESS_CONTROL_ASSISTANCE_OPS";
                    break;
                case "S-1-5-33":
                    name = "WRITE_RESTRICTED";
                    break;
                case "S-1-5-64-10":
                    name = "NTLM_AUTHENTICATION";
                    break;
                case "S-1-5-64-14":
                    name = "SCHANNEL_AUTHENTICATION";
                    break;
                case "S-1-5-64-21":
                    name = "DIGEST_AUTHENTICATION";
                    break;
                case "S-1-5-65-1":
                    name = "THIS_ORGANIZATION_CERTIFICATE";
                    break;
                case "S-1-5-80":
                    name = "NT_SERVICE";
                    break;
                case "S-1-5-84-0-0-0-0-0":
                    name = "USER_MODE_DRIVERS";
                    break;
                case "S-1-5-1000":
                    name = "OTHER_ORGANIZATION";
                    break;
                case "S-1-15-2-1":
                    name = "ALL_APP_PACKAGES";
                    break;
                case "S-1-16-0":
                    name = "ML_UNTRUSTED";
                    break;
                case "S-1-16-4096":
                    name = "ML_LOW";
                    break;
                case "S-1-16-8192":
                    name = "ML_MEDIUM";
                    break;
                case "S-1-16-8448":
                    name = "ML_MEDIUM_PLUS";
                    break;
                case "S-1-16-12288":
                    name = "ML_HIGH";
                    break;
                case "S-1-16-16384":
                    name = "ML_SYSTEM";
                    break;
                case "S-1-16-20480":
                    name = "ML_PROTECTED_PROCESS";
                    break;
                default:
                    name = "Not found.(Token=" + sid + ")";
                    break;
            }
            return name;
        }

        private string GetEntry(byte[] token)
        {
            try
            {
                DirectoryEntry root = new DirectoryEntry(this.ldap, this.id, this.pw);
                IdentityReferenceCollection identityReferenceCollection = new IdentityReferenceCollection();
                identityReferenceCollection.Add(new SecurityIdentifier(token, 0));

                identityReferenceCollection = identityReferenceCollection.Translate(typeof(NTAccount));
                string name = "";                
                foreach (NTAccount account in identityReferenceCollection)
                {
                    name = account.Value;
                }
                return name;
            }
            catch
            {
                return this.GetSystemSid(this.ToObjectSidString(token));
            }
        }

        private string ldap = "";
        private string id = "";
        private string pw = "";
        private bool login = false;
        public void setInfo(string _ladp, string _id, string _pw)
        {
            this.ldap = _ladp;
            this.id = _id;
            this.pw = _pw;
            this.login = true;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (this.checkBox1.Checked)
            {
                this.login = false;
                Form2 f = new Form2();
                f.serForm(this);
                f.ShowDialog();
                if (this.login == false)
                {
                    return;
                }
            }

            this.listBox1.Items.Clear();

            string data = this.textBox1.Text.Trim();

            if (data.StartsWith("0x"))
            {
                data = this.textBox1.Text.Substring(2).Trim();
            }
            else
            {
                data = this.textBox1.Text.Trim();
            }

            byte[] bsize = new byte[data.Length / 2];
            int pos = 0;
            for (int cnt = 0; cnt < bsize.Length; cnt++)
            {
                string v = data.Substring(pos, 2);
                int i = Convert.ToInt32(v, 16);
                byte b = Convert.ToByte(i);
                bsize[cnt] = b;
                pos = pos + 2;
            }

            byte[] token = bsize;

            Dictionary<string, string> dict = null;

            if (this.IsFormAuth(token))
            {
                dict = this.AnalyzeTokenFormAuth(token);
            }
            else
            {
                dict = this.AnalyzeTokenAD(token);
            }

            foreach (string key in dict.Keys)
            {
                string val = dict[key];
                this.listBox1.Items.Add(key + "=" + val);
            }
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            this.listBox1.Height = this.splitContainer1.Panel2.Height;
            this.listBox1.Width = this.splitContainer1.Panel2.Width;
        }
    }
}
